using System;
using System.Collections;
using UnityEngine;

[Serializable]
public class FlightInitialConditionsSearch
{
	[Serializable]
	public class SearchBoundaryFloat : IEnumerable
	{
		public float min;

		public float max;

		public int steps;

		IEnumerator IEnumerable.GetEnumerator()
		{
			if (steps > 1)
			{
				for (int i = 0; i < steps - 1; i++)
				{
					yield return Mathf.Lerp(min, max, (float)i / (float)(steps - 1));
				}
			}
			yield return max;
		}
	}

	public struct SimulationResult
	{
		public Vector3 velocity;

		public Vector3 angularVelocity;

		public Vector3 position;

		public float distance;

		public float heightOverNet;

		public Vector3 landingPos;

		public float timeToLand;

		public float maxHeight;

		public int steps;

		public FlightParams endParams;

		public bool isLandedOnTable
		{
			get
			{
				return Mathf.Abs(landingPos.z) != 0f && Mathf.Sign(position.z) != Mathf.Sign(landingPos.z) && Table.IsPosOnTable(landingPos);
			}
		}
	}

	public delegate void SearchObserverDelegate(Vector3 prevPos, Vector3 curPos, SimulationResult simRes, bool done);

	public enum SimResultClasification
	{
		Long = 0,
		Short = 1,
		In = 2
	}

	public struct SimResult
	{
		public float magnitude;

		public SimulationResult simResult;

		public SimResultClasification resultClasification;
	}

	private enum BounceType
	{
		BounceBeforeNet = 0,
		BounceAfterNet = 1
	}

	public struct MaxResult
	{
		public float magnitude;

		public int totalSteps;

		public SimResult simResult;
	}

	public enum OptimumSearchType
	{
		SearchMax = 0,
		SearchMin = 1
	}

	public static FlightInitialConditionsSearch _defaultInstance;

	public SearchObserverDelegate searchObserverDelegate;

	public SearchBoundaryFloat aimBoundaries = new SearchBoundaryFloat();

	public SearchBoundaryFloat velocityMagnitudeBoundaries = new SearchBoundaryFloat();

	public SearchBoundaryFloat angularVelocityMagnitudeBoundaries = new SearchBoundaryFloat();

	public SearchBoundaryFloat heightBoundaries = new SearchBoundaryFloat();

	public FlightParams incomingParams;

	public Vector3 forwardDirection;

	public int maxStepsAtOnce;

	public float symDeltaTime;

	public BallFlight symFlight;

	public Ball ball;

	public bool searchWhenMissTable;

	private FlightSimulator.EndConditionsList endConditionsList = new FlightSimulator.EndConditionsList();

	public static FlightInitialConditionsSearch instance
	{
		get
		{
			if (_defaultInstance == null)
			{
				_defaultInstance = new FlightInitialConditionsSearch();
				_defaultInstance.velocityMagnitudeBoundaries.max = 20f;
				_defaultInstance.velocityMagnitudeBoundaries.steps = 10;
				_defaultInstance.heightBoundaries.max = 10f;
				_defaultInstance.symFlight = new MagnusForceAndAirResistanceSquaredBallFlight();
				_defaultInstance.symDeltaTime = 0.1f;
			}
			return _defaultInstance;
		}
	}

	public void SetupWithHumanRanges(Vector3 forwardDirection, Vector3 position, BallFlight symFlight)
	{
		velocityMagnitudeBoundaries.max = 20f;
		heightBoundaries.max = 10f;
		symDeltaTime = 0.1f;
		this.symFlight = symFlight;
		Setup(forwardDirection, position);
	}

	public void Setup(Vector3 forwardDirection, Vector3 position)
	{
		this.forwardDirection = forwardDirection;
		incomingParams.position = position;
	}

	public IEnumerator Search()
	{
		int steps = 0;
		IEnumerator enumerator = ((IEnumerable)angularVelocityMagnitudeBoundaries).GetEnumerator();
		try
		{
			while (enumerator.MoveNext())
			{
				float angularVelocityMagnitude = (float)enumerator.Current;
				IEnumerator enumerator2 = ((IEnumerable)aimBoundaries).GetEnumerator();
				try
				{
					while (enumerator2.MoveNext())
					{
						float angle = (float)enumerator2.Current;
						IEnumerator enumerator3 = ((IEnumerable)velocityMagnitudeBoundaries).GetEnumerator();
						try
						{
							while (enumerator3.MoveNext())
							{
								float velocityMagnitude = (float)enumerator3.Current;
								if (steps >= maxStepsAtOnce && maxStepsAtOnce > 0)
								{
									steps = 0;
									yield return null;
								}
								SimulationResult simRes = Simulate(velocityMagnitude, angle, angularVelocityMagnitude);
							}
						}
						finally
						{
							IDisposable disposable;
							IDisposable disposable2 = (disposable = enumerator3 as IDisposable);
							if (disposable != null)
							{
								disposable2.Dispose();
							}
						}
					}
				}
				finally
				{
					IDisposable disposable;
					IDisposable disposable3 = (disposable = enumerator2 as IDisposable);
					if (disposable != null)
					{
						disposable3.Dispose();
					}
				}
			}
		}
		finally
		{
			IDisposable disposable;
			IDisposable disposable4 = (disposable = enumerator as IDisposable);
			if (disposable != null)
			{
				disposable4.Dispose();
			}
		}
	}

	public SimResult FindVelocityResultForServe(float velocityMagnitude, float angle, float angularVelocityMagnitude)
	{
		FlightParams initialConditions = GetInitialConditions(velocityMagnitude, angle, angularVelocityMagnitude);
		SimResult result = FindVelocityResult(initialConditions, BounceType.BounceBeforeNet);
		if (result.resultClasification != SimResultClasification.In)
		{
			return result;
		}
		initialConditions = result.simResult.endParams;
		SimResult result2 = FindVelocityResult(initialConditions, BounceType.BounceAfterNet);
		result2.simResult.steps += result.simResult.steps;
		result2.magnitude = result.magnitude;
		return result2;
	}

	public SimResult FindVelocityResultForReturn(float velocityMagnitude, float angle, float angularVelocityMagnitude)
	{
		FlightParams initialConditions = GetInitialConditions(velocityMagnitude, angle, angularVelocityMagnitude);
		return FindVelocityResult(initialConditions, BounceType.BounceAfterNet);
	}

	private SimResult FindVelocityResult(FlightParams initParams, BounceType bounceType)
	{
		SimResult result = default(SimResult);
		result.magnitude = initParams.velocity.magnitude;
		SimulationResult simulationResult = (result.simResult = Simulate(initParams));
		float num = simulationResult.maxHeight - (Table.tabletopy - Table.netHeight);
		SimResultClasification resultClasification;
		if (bounceType == BounceType.BounceAfterNet && num < heightBoundaries.min)
		{
			resultClasification = ((!(simulationResult.endParams.velocity.y >= 0f)) ? SimResultClasification.Short : SimResultClasification.Long);
		}
		else if (num > heightBoundaries.max)
		{
			resultClasification = SimResultClasification.Long;
		}
		else if (Mathf.Sign(forwardDirection.z) * simulationResult.landingPos.z >= 0f && Table.IsNetHit(simulationResult.heightOverNet - symFlight.radius))
		{
			resultClasification = ((bounceType == BounceType.BounceAfterNet && !(simulationResult.endParams.velocity.y >= 0f)) ? SimResultClasification.Short : SimResultClasification.Long);
		}
		else if (bounceType == BounceType.BounceAfterNet && Mathf.Sign(forwardDirection.z) * simulationResult.landingPos.z <= 0f)
		{
			resultClasification = SimResultClasification.Short;
		}
		else if (bounceType == BounceType.BounceBeforeNet && Mathf.Sign(forwardDirection.z) * simulationResult.landingPos.z >= 0f)
		{
			resultClasification = SimResultClasification.Long;
		}
		else if (Table.IsPosOnTable(simulationResult.landingPos))
		{
			resultClasification = SimResultClasification.In;
		}
		else
		{
			resultClasification = SimResultClasification.Long;
			Vector3 position = initParams.position;
			TableIntersectionSearch tableIntersectionSearch = Singleton<TableIntersectionSearch>.instance;
			tableIntersectionSearch.FindIntersectionsWithTable(position, forwardDirection.OnGround(), Mathf.Sign(forwardDirection.z));
			if (tableIntersectionSearch.isIntersectionFound && Vector3Ex.HorizontalDistance(simulationResult.landingPos, position) < Vector3Ex.HorizontalDistance(tableIntersectionSearch.enter.position, position))
			{
				resultClasification = SimResultClasification.Short;
			}
		}
		result.resultClasification = resultClasification;
		return result;
	}

	public SimResult FindAimResult(float angle, float speed, float angularVelocityMagnitude, float aimHeight, float angleHeightAboveTable, Vector3 position)
	{
		SimResult result = default(SimResult);
		result.magnitude = angle;
		angle = GetAngle(angle, angleHeightAboveTable, position);
		SimulationResult simulationResult = (result.simResult = Simulate(speed, angle, angularVelocityMagnitude));
		float num = simulationResult.maxHeight - (Table.tabletopy - Table.netHeight);
		SimResultClasification resultClasification;
		if (num < heightBoundaries.min)
		{
			resultClasification = SimResultClasification.Short;
		}
		else if (num > heightBoundaries.max)
		{
			resultClasification = SimResultClasification.Long;
		}
		else if (Mathf.Sign(forwardDirection.z) * simulationResult.landingPos.z < 0f)
		{
			resultClasification = SimResultClasification.Short;
		}
		else if (Table.IsNetHit(simulationResult.heightOverNet - symFlight.radius))
		{
			resultClasification = ((simulationResult.heightOverNet + symFlight.radius < aimHeight) ? SimResultClasification.Short : SimResultClasification.In);
		}
		else
		{
			resultClasification = SimResultClasification.Long;
			Vector3 position2 = incomingParams.position;
			TableIntersectionSearch tableIntersectionSearch = Singleton<TableIntersectionSearch>.instance;
			tableIntersectionSearch.FindIntersectionsWithTable(position2, forwardDirection.OnGround(), Mathf.Sign(forwardDirection.z));
			if (tableIntersectionSearch.isIntersectionFound && Vector3Ex.HorizontalDistance(simulationResult.landingPos, position2) < Vector3Ex.HorizontalDistance(tableIntersectionSearch.enter.position, position2))
			{
				resultClasification = SimResultClasification.Short;
			}
		}
		result.resultClasification = resultClasification;
		return result;
	}

	public MaxResult FindMaxAcceptableVelocity(float angle, float angularVelocityMagnitude, OptimumSearchType searchType, bool isServe = false)
	{
		float max = velocityMagnitudeBoundaries.max;
		float min = velocityMagnitudeBoundaries.min;
		float velocityMagnitude = (max + min) * 0.5f;
		SimResult simResult = ((!isServe) ? FindVelocityResultForReturn(max, angle, angularVelocityMagnitude) : FindVelocityResultForServe(max, angle, angularVelocityMagnitude));
		SimResult simResult2 = ((!isServe) ? FindVelocityResultForReturn(min, angle, angularVelocityMagnitude) : FindVelocityResultForServe(min, angle, angularVelocityMagnitude));
		SimResult simResult3 = ((!isServe) ? FindVelocityResultForReturn(velocityMagnitude, angle, angularVelocityMagnitude) : FindVelocityResultForServe(velocityMagnitude, angle, angularVelocityMagnitude));
		int num = simResult.simResult.steps + simResult2.simResult.steps + simResult3.simResult.steps;
		int num2 = 15;
		for (int i = 0; i < num2; i++)
		{
			if (searchType == OptimumSearchType.SearchMax)
			{
				if (simResult2.resultClasification == SimResultClasification.Short && simResult3.resultClasification == SimResultClasification.Short)
				{
					simResult2 = simResult3;
				}
				else if (simResult.resultClasification == SimResultClasification.Long && simResult3.resultClasification == SimResultClasification.Long)
				{
					simResult = simResult3;
				}
				else if (simResult3.resultClasification == SimResultClasification.In && (simResult2.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.In))
				{
					simResult2 = simResult3;
				}
				else if (simResult.resultClasification == SimResultClasification.In || simResult.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.Long)
				{
					break;
				}
			}
			else if (simResult2.resultClasification == SimResultClasification.Short && simResult3.resultClasification == SimResultClasification.Short)
			{
				simResult2 = simResult3;
			}
			else if (simResult.resultClasification == SimResultClasification.Long && simResult3.resultClasification == SimResultClasification.Long)
			{
				simResult = simResult3;
			}
			else if (simResult3.resultClasification == SimResultClasification.In && (simResult.resultClasification == SimResultClasification.Long || simResult.resultClasification == SimResultClasification.In))
			{
				simResult = simResult3;
			}
			else if (simResult2.resultClasification == SimResultClasification.In || simResult.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.Long)
			{
				break;
			}
			simResult3 = ((!isServe) ? FindVelocityResultForReturn((simResult.magnitude + simResult2.magnitude) * 0.5f, angle, angularVelocityMagnitude) : FindVelocityResultForServe((simResult.magnitude + simResult2.magnitude) * 0.5f, angle, angularVelocityMagnitude));
			num += simResult3.simResult.steps;
		}
		MaxResult result = default(MaxResult);
		float magnitude = simResult.magnitude;
		if (searchType == OptimumSearchType.SearchMax)
		{
			if (simResult.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult.magnitude;
				result.simResult = simResult;
			}
			else if (simResult3.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult3.magnitude;
				result.simResult = simResult3;
			}
			else if (simResult2.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult2.magnitude;
				result.simResult = simResult2;
			}
		}
		else if (simResult2.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult2.magnitude;
			result.simResult = simResult2;
		}
		else if (simResult3.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult3.magnitude;
			result.simResult = simResult3;
		}
		else if (simResult.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult.magnitude;
			result.simResult = simResult;
		}
		result.magnitude = magnitude;
		result.totalSteps = num;
		return result;
	}

	public MaxResult FindMaxAimHeightAboveNet(float speed, float angularVelocityMagnitude, float netHeightToHit, float aimHeightAboveTable, Vector3 position, OptimumSearchType searchType)
	{
		float max = aimBoundaries.max;
		float min = aimBoundaries.min;
		float angle = (max + min) * 0.5f;
		SimResult simResult = FindAimResult(max, speed, angularVelocityMagnitude, netHeightToHit, aimHeightAboveTable, position);
		SimResult simResult2 = FindAimResult(min, speed, angularVelocityMagnitude, netHeightToHit, aimHeightAboveTable, position);
		SimResult simResult3 = FindAimResult(angle, speed, angularVelocityMagnitude, netHeightToHit, aimHeightAboveTable, position);
		int num = simResult.simResult.steps + simResult2.simResult.steps + simResult3.simResult.steps;
		int num2 = 15;
		for (int i = 0; i < num2; i++)
		{
			if (searchType == OptimumSearchType.SearchMax)
			{
				if (simResult2.resultClasification == SimResultClasification.Short && simResult3.resultClasification == SimResultClasification.Short)
				{
					simResult2 = simResult3;
				}
				else if (simResult.resultClasification == SimResultClasification.Long && simResult3.resultClasification == SimResultClasification.Long)
				{
					simResult = simResult3;
				}
				else if (simResult3.resultClasification == SimResultClasification.In && (simResult2.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.In))
				{
					simResult2 = simResult3;
				}
				else if (simResult.resultClasification == SimResultClasification.In || simResult.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.Long)
				{
					break;
				}
			}
			else if (simResult2.resultClasification == SimResultClasification.Short && simResult3.resultClasification == SimResultClasification.Short)
			{
				simResult2 = simResult3;
			}
			else if (simResult.resultClasification == SimResultClasification.Long && simResult3.resultClasification == SimResultClasification.Long)
			{
				simResult = simResult3;
			}
			else if (simResult3.resultClasification == SimResultClasification.In && (simResult.resultClasification == SimResultClasification.Long || simResult.resultClasification == SimResultClasification.In))
			{
				simResult = simResult3;
			}
			else if (simResult2.resultClasification == SimResultClasification.In || simResult.resultClasification == SimResultClasification.Short || simResult2.resultClasification == SimResultClasification.Long)
			{
				break;
			}
			simResult3 = FindAimResult((simResult.magnitude + simResult2.magnitude) * 0.5f, speed, angularVelocityMagnitude, netHeightToHit, aimHeightAboveTable, position);
			num += simResult3.simResult.steps;
		}
		float magnitude = simResult.magnitude;
		if (searchType == OptimumSearchType.SearchMax)
		{
			if (simResult.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult.magnitude;
			}
			else if (simResult3.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult3.magnitude;
			}
			else if (simResult2.resultClasification == SimResultClasification.In)
			{
				magnitude = simResult2.magnitude;
			}
		}
		else if (simResult2.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult2.magnitude;
		}
		else if (simResult3.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult3.magnitude;
		}
		else if (simResult.resultClasification == SimResultClasification.In)
		{
			magnitude = simResult.magnitude;
		}
		MaxResult result = default(MaxResult);
		result.magnitude = magnitude;
		result.totalSteps = num;
		return result;
	}

	public void SearchWithoutStopping()
	{
		IEnumerator enumerator = Search();
		while (enumerator.MoveNext())
		{
		}
	}

	public FlightParams GetInitialConditions(float velocityMagnitude, float angle, float angularVelocityMagnitude)
	{
		FlightParams result = default(FlightParams);
		result.position = incomingParams.position;
		Vector3 normalized = Vector3.Cross(forwardDirection, Vector3.up).normalized;
		result.velocity = Quaternion.AngleAxis(angle, Vector3.Cross(forwardDirection, Vector3.up).normalized) * forwardDirection * velocityMagnitude;
		result.angularVelocity = -normalized * angularVelocityMagnitude;
		return result;
	}

	public FlightParams GetInitialConditions(float velocityMagnitude, float angle, float angularVelocityMagnitude, Vector3 additionalAngularVelocity)
	{
		FlightParams result = default(FlightParams);
		result.position = incomingParams.position;
		Vector3 normalized = Vector3.Cross(forwardDirection, Vector3.up).normalized;
		result.velocity = Quaternion.AngleAxis(angle, Vector3.Cross(forwardDirection, Vector3.up).normalized) * forwardDirection * velocityMagnitude;
		result.angularVelocity = -normalized * angularVelocityMagnitude + additionalAngularVelocity;
		return result;
	}

	protected virtual SimulationResult Simulate(float velocityMagnitude, float angle, float angularVelocity)
	{
		FlightParams initialConditions = GetInitialConditions(velocityMagnitude, angle, angularVelocity);
		return Simulate(initialConditions);
	}

	protected virtual SimulationResult Simulate(FlightParams initialParams)
	{
		SimulationResult simulationResult = default(SimulationResult);
		simulationResult.position = initialParams.position;
		symFlight.SetInitialConditions(initialParams, null);
		symFlight.Reset();
		int maxSimulatorIterations = 1000;
		int num = 0;
		bool flag = false;
		bool flag2 = false;
		FlightParams p = symFlight.FlightParams();
		FlightParams flightParams;
		FlightParams flightParams2;
		bool flag4;
		FlightParams flightParams3;
		while (true)
		{
			flightParams = symFlight.FlightParams();
			symFlight.Update(symDeltaTime);
			flightParams2 = symFlight.FlightParams();
			endConditionsList.Clear();
			flag2 = flag2 || flightParams2.position.y >= Table.tabletopy;
			bool flag3 = Mathf.Sign(flightParams.position.z) != Mathf.Sign(flightParams2.position.z);
			flag4 = false;
			flightParams3 = default(FlightParams);
			if (flag3)
			{
				float guess = Mathf.Abs(flightParams.position.z) / Mathf.Abs(flightParams2.position.z - flightParams.position.z);
				guess = MathEx.CatmullRomInverseLerp(p.position.z, flightParams.position.z, flightParams2.position.z, flightParams2.position.z, 0f, guess);
				flightParams3 = FlightParams.CatmullRomLerp(p, flightParams, flightParams2, flightParams2, guess);
				float y = flightParams3.position.y;
				simulationResult.heightOverNet = y - symFlight.radius;
				flag4 = Table.IsNetHit(simulationResult.heightOverNet - symFlight.radius);
				if (flag4)
				{
					flightParams2 = flightParams3;
				}
				flag = true;
			}
			num++;
			float num2 = Table.tabletopy + symFlight.radius;
			bool flag5 = StopSimForTableMissed(flightParams2.position, num2, flag) || IsBelowFloor(flightParams2.position, num2) || IsMaxIterationsReached(num, maxSimulatorIterations) || IsBelowTable(flightParams2.position, flag2) || flag4;
			simulationResult.maxHeight = Mathf.Max(simulationResult.maxHeight, flightParams2.position.y);
			if (flag5)
			{
				float t = 1f;
				if (flag4)
				{
					simulationResult.landingPos = flightParams2.position;
					simulationResult.landingPos.z = 0f;
				}
				else if (IsBelowFloor(flightParams2.position, num2) && flag)
				{
					t = Mathf.Abs(num2 - flightParams.position.y) / Mathf.Abs(flightParams2.position.y - flightParams.position.y);
					t = MathEx.CatmullRomInverseLerp(p.position.y, flightParams.position.y, flightParams2.position.y, flightParams2.position.y, num2, t);
					simulationResult.landingPos = Vector3Ex.CatmullRomLerp(p.position, flightParams.position, flightParams2.position, flightParams2.position, t);
					flightParams2.position = simulationResult.landingPos;
				}
				else
				{
					simulationResult.landingPos = flightParams2.position;
				}
				simulationResult.timeToLand = symFlight.flightTime - symDeltaTime + Mathf.Lerp(0f, symDeltaTime, t);
				simulationResult.steps = num;
			}
			if (searchObserverDelegate != null)
			{
				searchObserverDelegate(flightParams.position, flightParams2.position, simulationResult, flag5);
			}
			if (flag5)
			{
				break;
			}
			p = flightParams;
		}
		float num3 = Table.tabletopy + symFlight.radius;
		float guess2 = Mathf.Abs(num3 - flightParams.position.y) / Mathf.Abs(flightParams2.position.y - flightParams.position.y);
		guess2 = MathEx.CatmullRomInverseLerp(p.position.y, flightParams.position.y, flightParams2.position.y, flightParams2.position.y, num3, guess2);
		FlightParams paramsBeforeBounce = FlightParams.CatmullRomLerp(p, flightParams, flightParams2, flightParams2, guess2);
		bool flag6 = Table.IsPosOnTable(paramsBeforeBounce.position);
		if (flag4)
		{
			paramsBeforeBounce = symFlight.FlightParams();
			paramsBeforeBounce.position = flightParams3.position;
			paramsBeforeBounce.position.z = 0f;
			simulationResult.endParams = paramsBeforeBounce;
		}
		else if (flag6)
		{
			paramsBeforeBounce.position.y = Table.tabletopy + symFlight.radius;
			simulationResult.endParams = CollisionHandlerFactory.GetBallFlightParamsAfterBounce(CollisionHandlerFactory.CollisionType.CollideWithTable, paramsBeforeBounce, symFlight.mass, symFlight.radius);
		}
		else
		{
			simulationResult.endParams = symFlight.FlightParams();
		}
		return simulationResult;
	}

	private bool IsBelowFloor(Vector3 curPos, float floor)
	{
		return curPos.y <= floor;
	}

	private bool StopSimForTableMissed(Vector3 curPos, float floor, bool crossedNet)
	{
		return IsTableMissed(curPos, floor, crossedNet) && !searchWhenMissTable;
	}

	private bool IsTableMissed(Vector3 curPos, float floor, bool crossedNet)
	{
		return (IsBelowFloor(curPos, floor) || crossedNet) && Mathf.Abs(curPos.z) > Table.halfLength;
	}

	private bool IsBelowTable(Vector3 curPos, bool crossedTableTop)
	{
		return !crossedTableTop && Table.IsPosOnTable(curPos);
	}

	private bool IsMaxIterationsReached(int simulatorIteration, int maxSimulatorIterations)
	{
		return simulatorIteration > maxSimulatorIterations;
	}

	public static float GetAngle(float aimHeightAboveNet, float aimHeightAboveTable, Vector3 position)
	{
		float num = Table.tabletopy + Table.netHeight + aimHeightAboveNet - position.y;
		float num2 = Mathf.Sign(num) * Vector3.Angle(new Vector3(0f, 0f, 1f), new Vector3(0f, num, Mathf.Abs(position.z)));
		if (Mathf.Abs(position.z) > Table.halfLength && position.y < Table.tabletopy)
		{
			num2 = Mathf.Max(num2, Vector3.Angle(new Vector3(0f, 0f, 1f), new Vector3(0f, Table.tabletopy + aimHeightAboveTable - position.y, Mathf.Abs(position.z) - Table.halfLength)));
		}
		return num2;
	}
}
